#ifndef ARBOL_HEADER
#define ARBOL_HEADER

#include <list>
#include <iostream>

using namespace std;

template <class T>
class Arbol
{
	public:
		Arbol();
		~Arbol();

		class Nodo
		{
			public:
        Nodo();
				Nodo(T& e);
				~Nodo();
				void agregarHijo(Nodo& hijo);
				void mostrar (ostream& os, int offset);

				friend ostream& operator<<(ostream& os, Nodo& n)
				{
				  n.mostrar(os,0);
				  return os;
				};

				T& elemento();

			private:
				T* elem;
				list<Nodo*> hijos;
		};

    void establecerRaiz(Nodo& n);
    void mostrar(ostream& o);

    friend ostream& operator<<(ostream& os, Arbol& a)
		{
		  a.mostrar(os);
		  return os;
		};

	private:
    Nodo* raiz;
};

template <class T>
Arbol<T>::Arbol()
{
  raiz = NULL;
}

template <class T>
Arbol<T>::~Arbol()
{
}

template <class T>
void Arbol<T>::establecerRaiz(Nodo& n)
{
  raiz = &n;
}

template <class T>
Arbol<T>::Nodo::Nodo()
{
}

template <class T>
Arbol<T>::Nodo::~Nodo()
{
}

template <class T>
Arbol<T>::Nodo::Nodo(T& e)
{
  elem = &e;
}

template <class T>
void Arbol<T>::Nodo::agregarHijo(typename Arbol<T>::Nodo& hijo)
{
  hijos.push_back(&hijo);
}

template <class T>
T& Arbol<T>::Nodo::elemento()
{
  return *elem;
}

template <class T>
void Arbol<T>::mostrar(ostream& os)
{
  (*raiz).mostrar(os,0);
}

template <class T>
void Arbol<T>::Nodo::mostrar(ostream& os, int offset)
{
  int delta_offset = 3;


  if(offset == delta_offset){offset+=3;}
  os.width(offset);

  os << right << "+--"<< *elem << endl;


 //cout << endl << right << "( principio hijos de: " << *elem << ")" << endl;
  for (typename list<typename Arbol<T>::Nodo*>::iterator it = hijos.begin();
    it != hijos.end(); it++)
  {
    (**it).mostrar(os, offset+ delta_offset);
  }
 // cout << right << "( fin hijos de: " << *elem << ")" << endl;


}

#endif // ARBOL_HEADER
